package com.kuizii.server.discovery;

import com.kuizii.common.LiteServiceRegistration;
import com.kuizii.common.exception.LiteSecurityException;
import com.kuizii.common.net.EventType;
import com.kuizii.server.net.IOManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author renxiaodong
 */

@Component
public class NettyRegisterEventListener implements RegisterEventListener, ApplicationListener<RegisterEvent> {

    static final Logger logger = LoggerFactory.getLogger(DefaultRegisterServer.class);
    List<RegisterEvent> eventHandlerList = new ArrayList<>();
    SecurityHandler securityHandler;
    IOManager ioManager;

    public NettyRegisterEventListener(SecurityHandler securityHandler, IOManager ioManager) {
        this.securityHandler = securityHandler;
        this.ioManager = ioManager;

//        init();
    }

    /**
     * KEY 服务名  value 实例列表
     */
    ConcurrentHashMap<String, Set<LiteServiceRegistration>> serviceMap = new ConcurrentHashMap<>();

    public void addEventHandler(RegisterEvent event) {
        eventHandlerList.add(event);
    }


    public void triggerEvent(EventType eventType, Object o) {
        List<Function> functions = eventHandlerList.stream().filter(x -> x.getEventType().equals(eventType)).map(x -> x.getCallBack()).collect(Collectors.toList());
        functions.forEach(x -> x.apply(o));
    }

    @Override
    public void onApplicationEvent(RegisterEvent registerEvent) {

        if (registerEvent.getEventType() == EventType.REGISTER) {
            register(registerEvent.getRegistration());
        } else if (registerEvent.getEventType() == EventType.DEREGISTER) {
            deregister(registerEvent.getRegistration());
        } else if (registerEvent.getEventType() == EventType.HEALTH_CHECK) {
            refresh(registerEvent.getRegistration());
        } else if (registerEvent.getEventType() == EventType.DESTROY) {
            deregister(registerEvent.getRegistration());
        }
    }


    /**
     * 注册服务
     *
     * @param registration
     */
    @Override
    public void register(LiteServiceRegistration registration) {
        if (!check(registration)) {
            return;
        }

        String serviceId = StringUtils.trimAllWhitespace(registration.getServiceId().toLowerCase(Locale.ROOT));

        //根据服务ID查询注册列表
        if (serviceMap.containsKey(serviceId)) {
            Set<LiteServiceRegistration> liteServiceInstances = serviceMap.get(serviceId);
            if (liteServiceInstances.stream().anyMatch(x -> x.getHost().equalsIgnoreCase(registration.getHost()) && x.getPort() == registration.getPort())) {
                return;
            } else {
                liteServiceInstances.add(registration);
                replicateToPeers();
            }
        } else {
            Set<LiteServiceRegistration> registrations = new HashSet<>();
            registrations.add(registration);
            serviceMap.put(serviceId, registrations);
            replicateToPeers();
        }
    }

    @Override
    public void refresh(LiteServiceRegistration registration) {

        register(registration);
    }

    @Override
    public void deregister(LiteServiceRegistration registration) {
        if (!check(registration)) {
            return;
        }
        String serviceId = StringUtils.trimAllWhitespace(registration.getServiceId().toLowerCase(Locale.ROOT));
        //根据服务ID查询注册列表
        if (serviceMap.containsKey(serviceId)) {
            Set<LiteServiceRegistration> liteServiceInstances = serviceMap.get(serviceId);
            if (CollectionUtils.isEmpty(liteServiceInstances)) {
                liteServiceInstances.removeIf(x -> x.getHost().equalsIgnoreCase(registration.getHost()) && x.getPort() == registration.getPort());
            }
        }
    }

    private boolean check(LiteServiceRegistration registration) {
        if (StringUtils.isEmpty(registration.getServiceId())) {
            logger.error("服务id传入为空，注册失败");

            return false;
        }
        //身份校验
        boolean match = securityHandler.isMatch(registration.getSecurityKey(), registration.getSecurityValue());
        if (!match) {
            throw new LiteSecurityException("lite注册身份检验失败！");
        }
        return true;
    }

    /**
     * 同步注册信息到其它注册中心节点
     */
    private void replicateToPeers() {

    }
}

